home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
FILER
/
SMART.ZIP
/
!SmartDir
/
c
/
pattern
< prev
Wrap
Text File
|
1998-01-15
|
8KB
|
351 lines
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "OS:osfile.h"
#include "OS:osfscontro.h"
#include "OS:osgbpb.h"
#include "cmos.h"
#include "pattern.h"
#ifndef NDEBUG
#include <stdarg.h>
#include <stdio.h>
#include "OS:wimp.h"
#endif
static char *patterns = 0;
static int patterns_size;
const os_error nomem_error = {0, "Not enough memory"};
const os_error nofile_error = {0, "File not found or is a directory"};
const os_error syntax_error = {0,
"*SmartOpenDir <full dirname> [<x> <y> [<width> <height>]] [<switches>]"};
/*static const os_error pattern_error = {0, "Bad pattern file"};*/
#ifndef NDEBUG
static void report(const char *report, ...)
{
os_error err;
va_list va;
va_start(va, report);
vsprintf(err.errmess, report, va);
va_end(va);
xwimp_report_error(&err, 1, "SmartOpenDir", 0);
}
#endif
os_error const *load_patterns(char const *filename)
{
int i;
os_error *e = xosfile_read_stamped(filename, &i, 0, 0,
&patterns_size, 0, 0);
if (e) return e;
if (i != 1)
return &nofile_error;
patterns = realloc(patterns, patterns_size + 1);
if (!patterns)
return &nomem_error;
e = xosfile_load_stamped(filename, (byte *) patterns,
0, 0, 0, 0, 0);
if (e) return e;
/* Change patterns to make it easier to process */
for (i = 0; i < patterns_size; ++i)
{
if (iscntrl(patterns[i]))
{
if (patterns[i] == '\t')
patterns[i] = ' ';
else
patterns[i] = 0;
}
else
patterns[i] = tolower(patterns[i]);
}
if (patterns[patterns_size - 1] != 0)
patterns[patterns_size++] = 0;
return 0;
}
void free_patterns()
{
free(patterns);
patterns = 0;
}
bool match_pattern(char const *directory, char const *pattern)
{
char canon[256]; /* Canonicalised directory name */
int i, j;
int lmi = -1, lmj = -1; /* Last place where i & j matched for * */
if (xosfscontrol_canonicalise_path(directory, canon, 0, 0, sizeof(canon), 0))
return FALSE;
#ifndef NDEBUG
report("Matching directory \"%s\" against pattern \"%s\"\n", canon, pattern);
#endif
for (i = 0, j = 0; ; )
{
switch (pattern[j])
{
case '*':
lmj = j++;
if (pattern[j] <= ' ')
return TRUE;
while (tolower(canon[i]) != pattern[j] && canon[i] > ' ')
++i;
if (canon[i] <= ' ')
return FALSE;
lmi = i;
break;
case '%':
while (canon[i] != '.' && canon[i] > ' ')
++i;
++j;
if (canon[i] <= ' ' && pattern[j] <= ' ')
return TRUE;
break;
case '#':
++j;
++i;
break;
case '\\':
++j;
default:
if (canon[i] <= ' ' && pattern[j] <= ' ')
return TRUE;
if (tolower(canon[i]) != pattern[j])
{
if (lmi == -1)
return FALSE;
else
{
i = ++lmi;
j = lmj;
break;
}
}
++i;
++j;
}
}
return FALSE;
}
/* Find directory name in command *tail* */
static os_error const *find_directory(char const *command,
char const **directory)
{
*directory = strstr(command, "-directory ");
if (*directory)
*directory += 11;
else
{
*directory = strstr(command, "-dir ");
if (*directory)
*directory += 5;
}
if (!*directory)
{
*directory = command;
if (*command == '-')
return &syntax_error;
}
return 0;
}
/* Find effective start of current line */
static int line_start(int i)
{
while (i < patterns_size)
{
/* Find end of current line */
/* Skip all blank lines */
while (i < patterns_size && !patterns[i]) ++i;
if (i == patterns_size)
return i;
/* Skip whitespace */
while (isspace(patterns[i])) ++i;
/* Skip comments */
if (patterns[i] == '#')
{
while (i < patterns_size && patterns[i++]);
/* Back round loop in case next line is also blank/comment */
continue;
}
#ifndef NDEBUG
report("Pattern line: \"%s\"\n", &patterns[i]);
#endif
return i;
}
return i;
}
static int next_line(int i)
{
/* Find end of current line */
while (i < patterns_size && patterns[i++]);
return i;
}
int match_patterns(char const *directory)
{
int i;
int cmos;
if (!patterns)
return -1;
for (i = 0; i < patterns_size; )
{
i = line_start(i);
if (match_pattern(directory, patterns + i))
{
/* Get cmos options from pattern */
/* Find end of pattern */
while (patterns[i] && !isspace(patterns[i]))
++i;
if (!patterns[i])
return -1;
/* Skip spaces and tabs */
while (patterns[i] && isspace(patterns[i]))
++i;
if (!patterns[i] || !isxdigit(patterns[i]) || !isxdigit(patterns[i+1]) ||
(patterns[i+2] && !isspace(patterns[i+2]) && !isxdigit(patterns[i+2])))
return -1;
sscanf(&patterns[i], "%x", &cmos);
return cmos;
}
i = next_line(i);
}
return -1;
}
#define SLSIZE 256
/* Simple test for whether a directory contains more than n entries */
/*
static bool dir_more_simple(const char *directory, int n)
{
bool result;
char *sl;
sl = malloc(SLSIZE);
if (!sl)
return FALSE;
result = (!xosgbpb_dir_entries(directory, (osgbpb_string_list *) sl, 1,
n, SLSIZE, 0, &n, 0) && n);
free(sl);
return result;
}
*/
static bool dir_more_complex(const char *directory, int n)
{
int count;
int total;
int index;
char *sl;
sl = malloc(SLSIZE + 256);
if (!sl)
return FALSE;
for (total = index = 0; index != -1 && total < n; )
{
if (xosgbpb_dir_entries(directory, (osgbpb_string_list *) sl, 64,
index, SLSIZE, 0, &count, &index))
{
free(sl);
return FALSE;
}
total += count;
}
free(sl);
return total > n;
}
bool match_and_set(char const *directory)
{
int cmos = match_patterns(directory);
int action = (cmos & 0xf000000) >> 24;
#ifndef NDEBUG
report("cmos = 0x%x\n", cmos);
#endif
if (cmos == -1)
return FALSE;
else if (cmos >= 0x1000000 && action == 1)
{
#ifndef NDEBUG
report("Counting dir contents\n");
#endif
if (dir_more_complex(directory, (cmos & 0xff0000) >> 16))
{
#ifndef NDEBUG
report("More than 0x%x, setting cmos to 0x%x\n", (cmos & 0xff0000) >> 16, cmos & 0xff);
#endif
cmos &= 0xff;
}
else
{
#ifndef NDEBUG
report("Fewer than 0x%x, setting cmos to 0x%x\n", (cmos & 0xff0000) >> 16, (cmos & 0xff00) >> 8);
#endif
cmos = (cmos & 0xff00) >> 8;
}
}
cmos_set(cmos);
return TRUE;
}
static const char FilerOpenDir[] = "%Filer_OpenDir ";
static const int lfod = sizeof(FilerOpenDir) - 1;
/* Convert original command tail to "%Filer_OpenDir ... " */
os_error const *convert_command(char const *command, char **newcom)
{
int i;
int cmos;
char const *dir;
os_error const *e;
static char com[256];
#ifndef NDEBUG
report("original command=\n\"%s\"\n", command);
#endif
strcpy(com, FilerOpenDir);
while (isspace(*command)) ++command;
if (iscntrl(*command))
{
*newcom = 0;
return &syntax_error;
}
/* Make command zero-terminated */
for (i = 0; !iscntrl(command[i]) || command[i] == '\t'; ++i)
{
if (command[i] == '\t')
com[i + lfod] = ' ';
else
com[i + lfod] = command[i];
}
com[i + lfod] = 0;
#ifndef NDEBUG
report("lfod = %d, command=\n\"%s\"\n", lfod, com);
#endif
*newcom = com;
e = find_directory(command, &dir);
if (e)
return e;
cmos = match_patterns(dir);
if (cmos != -1)
cmos_set(cmos);
return 0;
}